'use strict';
/**
 * 用户相关接口
 * 此云对象内的所有函数默认需要登录才能访问
 */
var vk; // 全局vk实例
// 涉及的表名

const dbName = require("../../dao/config.js");

var db = uniCloud.database(); // 全局数据库引用
var _ = db.command; // 数据库操作符
var $ = _.aggregate; // 聚合查询操作符
/**
 * 权限注意：
 * pub_ 开头的函数不需要登录即可访问 如：pub_getList
 * kh_ 开头的函数需要登录才能访问 如：kh_getList
 * sys_ 开头的函数需要授权指定权限才能访问 如：sys_getList
 * _ 开头的函数禁止前端访问 如：_before
 * 其他函数 默认均需要登录才能访问 如：getList（若将云对象文件放在pub目录下，则默认其他函数不需要登录即可访问，若放在sys目录下，则默认其他函数需要授权才能访问）
 */
var cloudObject = {
	isCloudObject: true, // 标记为云对象模式
	/**
	 * 请求前处理，主要用于调用方法之前进行预处理，一般用于拦截器、统一的身份验证、参数校验、定义全局对象等。
	 */
	_before: async function() {
		vk = this.vk; // 将vk定义为全局对象
		// let { customUtil, uniID, config, pubFun } = this.getUtil(); // 获取工具包
	},
	/**
	 * 请求后处理，主要用于处理本次调用方法的返回结果或者抛出的错误
	 */
	_after: async function(obj) {
		let { err, res } = obj;
		if (err) {
			return; // 如果方法抛出错误，直接return;不处理
		}
		return res;
	},
	/**
	 * 获取用户中心信息
	 * @url client/user.getUserCenter 前端调用的url参数地址
	 */
	getUserCenter: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		// 因为用户中心会显示未付款订单数量，此处执行下自动取消已过期的未付款订单
		await vk.daoCenter.orderDao.autoCancelOrder({
			user_id: uid
		});
		// 获取订单数量
		res.groupArr = await vk.daoCenter.orderDao.groupCountOrderByUserId(uid, {
			formData: {
				order_type: 0
			},
			columns: [
				{ key: "order_type", mode: "=" }
			]
		});
		// 获取优惠券数量
		res.couponNum = await vk.daoCenter.userCouponDao.count({
			status: 0,
			user_id: uid
		});
		// 尝试升级VIP
		res.vip = await this.autoReceiveVip();
		res.userInfo = await vk.daoCenter.userDao.findById(uid);
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取用户订单分组数量
	 * @url client/user.getMyOrderGroupNum 前端调用的url参数地址
	 */
	getMyOrderGroupNum: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res.groupArr = await vk.daoCenter.orderDao.groupCountOrderByUserId(uid, data);
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取当前登录用户信息
	 * @url client/user.getMyInfo 前端调用的url参数地址
	 */
	getMyInfo: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取当前登录会员信息
	 * @url client/user.getMyVipInfo 前端调用的url参数地址
	 */
	getMyVipInfo: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res.mchInfo = await vk.daoCenter.mchDao.find();
		// 获取累计消费（已确认收货或已完成的）
		res.sumReceiptAmount = await vk.daoCenter.orderDao.sumReceiptAmount(uid);
		// 获取累计消费（冻结中，未确认收货或未完成的）
		res.sumNotReceiptAmount = await vk.daoCenter.orderDao.sumNotReceiptAmount(uid);

		let vipLevelRule = res.mchInfo.vip_level_rule;
		let vip_lv = userInfo.vip_lv || 0;
		let nextLevelInfo = vk.pubfn.getListItem(vipLevelRule, "lv", vip_lv == 0 ? 1 : vip_lv+1);
		if (nextLevelInfo && vk.pubfn.isNotNull(nextLevelInfo.goods_ids)) {
			// 获取是否有购买过会员升级需要的商品
			res.isBuyVipGoods = await vk.daoCenter.userDao.checkBuyGoods({
				user_id: uid,
				goods_ids: nextLevelInfo.goods_ids
			});
		}
		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取当前登录用户的会员动态码
	 * @url client/user.getVipCode 前端调用的url参数地址
	 */
	getVipCode: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let my_invite_code = userInfo.my_invite_code;
		let time = Date.now();
		// 每次获取都要重新修改会员动态码,会员动态码为纯数字格式：用户编号+13时间戳+4位随机数
		let vipCode = my_invite_code + time + vk.pubfn.random(4);
		res.userInfo = await vk.daoCenter.userDao.updateAndReturn({
			whereJson: {
				_id: uid
			},
			dataJson: {
				vip_code: {
					code: vipCode,
					exp_time: time + 1000 * 90
				}
			}
		});
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取当前登录用户的余额收支记录
	 * @url client/user.getBalanceRec 前端调用的url参数地址
	 */
	getBalanceRec: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.baseDao.getTableData({
			dbName: dbName.balanceRec,
			data,
			whereJson: {
				user_id: uid, // 设置只能查看自己的记录
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取当前登录用户的积分收支记录
	 * @url client/user.getIntegralRec 前端调用的url参数地址
	 */
	getIntegralRec: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.baseDao.getTableData({
			dbName: dbName.integralRec,
			data,
			whereJson: {
				user_id: uid, // 设置只能查看自己的记录
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 修改用户基础信息
	 * @url client/user.updateUserBaseInfo 前端调用的url参数地址
	 */
	updateUserBaseInfo: async function(data) {
		let { uid, filterResponse, originalParam } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		// 允许被用户直接修改的字段
		let updateKeys = ["nickname", "avatar", "gender", "social_info", "birthday"];
		let dataJson = {};
		for (let i in updateKeys) {
			let key = updateKeys[i];
			if (vk.pubfn.isNotNull(data[key])) dataJson[key] = data[key];
		}

		let userInfo = await vk.baseDao.updateAndReturn({
			dbName: dbName.user,
			whereJson: {
				_id: uid
			},
			dataJson
		});
		delete userInfo.token;
		delete userInfo.password;
		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我的优惠券列表
	 * @url client/user.getCouponList 前端调用的url参数地址
	 */
	getCouponList: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.userCouponDao.getTableData({
			data,
			whereJson: {
				user_id: uid, // 只能查看自己的优惠券
			},
			// 副表列表
			foreignDB: [{
				dbName: dbName.mallCoupon,
				localKey: "coupon_id",
				foreignKey: "_id",
				as: "couponInfo",
				limit: 1
			}]
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 手动领取会员等级
	 * @url client/user.receiveVip 前端调用的url参数地址
	 */
	receiveVip: async function(data) {
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			lv
		} = data;
		let time = Date.now();
		let mchInfo = await vk.daoCenter.mchDao.find();
		let { vip_level_rule } = mchInfo;
		let item = vk.pubfn.getListItem(vip_level_rule, "lv", lv);

		let isUpgrade = await this._isUpgradeVip({
			vipInfo: item,
			userInfo
		});

		if (isUpgrade) {
			// 允许升级
			await vk.daoCenter.userDao.updateVipLv({
				userInfo,
				lv
			});
		}
		res.isUpgrade = isUpgrade;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 自动领取会员等级
	 * @url client/user.autoReceiveVip 前端调用的url参数地址
	 */

	autoReceiveVip: async function(data) {
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let time = Date.now();
		let mchInfo = await vk.daoCenter.mchDao.find();
		let { vip_level_rule } = mchInfo;
		// 从大到小循环
		for (let i = vip_level_rule.length - 1; i >= 0; i--) {
			let item = vip_level_rule[i];
			let isUpgrade = await this._isUpgradeVip({
				vipInfo: item,
				userInfo
			});
			if (isUpgrade) {
				// 允许升级
				await vk.daoCenter.userDao.updateVipLv({
					userInfo,
					lv: item.lv
				});
				res.isUpgrade = isUpgrade;
				res.vipInfo = item;
				res.msg = `恭喜您的会员等级已升级为 ${item.name}`;
				break;
			}
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 判断是否可以升级到该VIP等级
	 * @url client/user._isUpgradeVip 前端调用的url参数地址
	 */
	_isUpgradeVip: async function(data) {
		// 业务逻辑开始-----------------------------------------------------------
		let {
			vipInfo,
			userInfo
		} = data;
		let {
			lv, // 会员等级
			total_recharge_amount, // 升级条件 - 累计充值多少余额后，可以升到此等级 单位分：100=1元
			total_order_amount, // 升级条件 - 累计消费多少金额后，可以升到此等级（此金额包含现金+余额）单位分：100=1元
			goods_ids, // 升级条件 - 购买指定商品中的任意一个
		} = vipInfo;
		if (lv <= userInfo.vip_lv) {
			// 如果当前等级未高于用户目前等级，则直接返回false
			return false;
		}
		if (total_recharge_amount > 0 && userInfo.account_balance.total >= total_recharge_amount) {
			return true;
		}
		if (total_order_amount > 0) {
			// 获取累计消费多少金额
			let sumReceiptAmount = await vk.daoCenter.orderDao.sumReceiptAmount(userInfo._id);
			if (sumReceiptAmount >= total_order_amount) {
				return true;
			}
		}
		if (vk.pubfn.isNotNull(goods_ids)) {
			let isBuyVipGoods = await vk.daoCenter.userDao.checkBuyGoods({
				user_id: userInfo._id,
				goods_ids: goods_ids
			});
			if (isBuyVipGoods) return true;
		}

		// 业务逻辑结束-----------------------------------------------------------
		return false;
	},
	/**
	 * 收藏商品
	 * @url client/user.collectGoods 前端调用的url参数地址
	 */
	collectGoods: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			goods_id,
			type = 0, // 0 自动 1 添加 2 删除
		} = data;
		let count = await vk.daoCenter.userCollectDao.count({
			user_id: uid,
			goods_id
		});
		let mode = type;
		if (type == 0) {
			mode = count > 0 ? 2 : 1;
		}
		if (mode == 1) {
			if (count > 0) return { code: 0, msg: "已收藏", isCollect: true };
			await vk.daoCenter.userCollectDao.add({
				user_id: uid,
				goods_id
			});
			res.msg = "收藏成功";
			res.isCollect = true;
		} else if (mode == 2) {
			await vk.daoCenter.userCollectDao.del({
				user_id: uid,
				goods_id
			});
			res.msg = "移除成功";
			res.isCollect = false;
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我收藏的商品列表
	 * @url client/user.getCollectGoods 前端调用的url参数地址
	 */
	getCollectGoods: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.userCollectDao.getTableData({
			data,
			whereJson: {
				user_id: uid
			},
			// 副表列表
			foreignDB: [{
				dbName: dbName.goods,
				localKey: "goods_id",
				foreignKey: "_id",
				as: "goods",
				limit: 1,
				foreignDB: [{
					dbName: dbName.sku,
					localKey: "_id",
					foreignKey: "goods_id",
					as: "sku_list",
					limit: 500
				}]
			}]
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取可以公开领取的优惠券列表
	 * @url client/user.getMallCouponList 前端调用的url参数地址
	 */
	getMallCouponList: async function(data) {
		let userInfo = await this.getUserInfo();
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let time = Date.now();
		res = await vk.daoCenter.mallCouponDao.getTableData({
			data,
			whereJson: {
				status: 1,
				is_public: true,
			},
			// 副表列表
			foreignDB: [{
				dbName: "vk-user-coupon",
				localKey: "_id",
				foreignKey: "coupon_id",
				as: "myCoupon",
				limit: 1,
				whereJson: {
					user_id: uid,
				},
				sortArr: [{ name: "status", type: "asc" }],
			}]
		});
		// 循环判断优惠券是否领取
		for (let i = 0; i < res.rows.length; i++) {
			let item = res.rows[i];
			let {
				receive_start_time,
				receive_end_time,
				limit,
				receive_rule,
				myCoupon
			} = item;

			if (receive_rule.type === 1 && userInfo.vip_lv === 0) {
				item.receiveRes = {
					status: -1,
					msg: `仅限会员领取`
				};
				continue;
			}
			if (receive_rule.type === 2 && receive_rule.vip_ids.indexOf(userInfo.vip_lv) == -1) {
				item.hide = true;
				item.receiveRes = {
					status: -1,
					msg: `不可领取`
				};
				continue;
			}
			if (time < receive_start_time) {
				item.receiveRes = {
					status: -2,
					msg: `最早可领取时间：${vk.pubfn.timeFormat(receive_start_time)}`
				};
				item.receive_start_time_diff = receive_start_time - time;

				continue;
			}
			if (time > receive_end_time) {
				item.receiveRes = {
					status: -1,
					msg: `已失效`
				};
				continue;
			}
			if (limit == 1 && vk.pubfn.isNotNull(myCoupon) && myCoupon.status === 1) {
				item.hide = true;
				item.receiveRes = {
					status: -1,
					msg: `已使用`
				};
				continue;
			}
			if (vk.pubfn.isNotNull(myCoupon) && myCoupon.status === 0) {
				item.receiveRes = {
					status: 1,
					msg: `立即使用`
				};
				continue;
			}
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 领取优惠券
	 * @url client/user.receiveCoupon 前端调用的url参数地址
	 */
	receiveCoupon: async function(data) {
		let userInfo = await this.getUserInfo();
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			coupon_id
		} = data;
		let mallCouponInfo = await vk.daoCenter.mallCouponDao.findById(coupon_id);
		if (vk.pubfn.isNull(mallCouponInfo)) return { code: -1, msg: "优惠券不存在" };
		let time = Date.now();
		let {
			status,
			receive_start_time,
			receive_end_time,
			limit,
			is_public,
			receive_rule
		} = mallCouponInfo;
		if (status === -1) return { code: -1, msg: "优惠券已删除" };
		if (status === 0) return { code: -1, msg: "优惠券未上架" };
		if (!is_public) return { code: -1, msg: "该优惠券不可领取" };
		if (receive_rule.type === 1 && userInfo.vip_lv === 0) {
			return { code: -1, msg: "仅限会员领取" };
		}
		if (receive_rule.type === 2 && receive_rule.vip_ids.indexOf(userInfo.vip_lv) == -1) {
			return { code: -1, msg: "未符合领取条件" };
		}
		if (time < receive_start_time) {
			return { code: -1, msg: `最早可领取时间：${vk.pubfn.timeFormat(receive_start_time)}` };
		}
		if (time > receive_end_time) {
			return { code: -1, msg: `已过最晚领取时间：${vk.pubfn.timeFormat(receive_end_time)}` };
		}
		if (limit) {
			let num = await vk.daoCenter.userCouponDao.count({
				user_id: uid,
				coupon_id,
				source: 0
			});
			if (num >= limit) {
				return { code: -1, msg: `已达领取上限：最多只能领取${limit}张` };
			}
		}
		let integral;
		if (receive_rule.mode === 1 && receive_rule.integral > 0) {
			if (userInfo.account_integral.balance < receive_rule.integral) {
				let msg =
					`领取失败：积分不足，需要【${receive_rule.integral}】个积分，您当前只有【${userInfo.account_integral.balance}】个积分，还差【${receive_rule.integral - userInfo.account_integral.balance}】个积分`;
				return { code: -1, msg };
			}
			integral = receive_rule.integral;
		}

		// 开启事务
		const transaction = await vk.baseDao.startTransaction();
		try {
			let remark = "";
			if (integral > 0) {
				let no = vk.pubfn.createOrderNo("NO");
				await vk.daoCenter.moneyDao.updateAccountIntegralForTransaction({
					db: transaction,
					user_id: userInfo._id,
					value: integral, // 此值始终为正整数 100=1元
					isAdd: false, // true 增加 false 减少
					no: no,
					title: `领取优惠券消耗`,
					comment: ``,
					add_type: 3, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
					updateTotal: false,
				});
				remark = `${integral}积分兑换`;
			}
			// 发放优惠券
			let addCouponRes = await vk.daoCenter.userCouponDao.addCoupon({
				db: transaction,
				coupon_id: coupon_id, // 优惠券id
				user_id: uid, // 用户id
				num: 1, // 发放数量
				source: 0, // 来源 0：自主领取 1：商家主动赠送 2：系统发放（如活动赠送等）
				remark, // 发放备注
			});
			if (addCouponRes.code !== 0) {
				// 事务回滚
				console.log("事务回滚", addCouponRes)
				await transaction.rollback();
				return addCouponRes;
			}
			res.msg = "领取成功";
			// 提交事务
			await transaction.commit();
			console.log(`transaction succeeded`);
		} catch (err) {
			// 事务回滚
			return await vk.baseDao.rollbackTransaction({
				db: transaction,
				err
			});
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 模板函数
	 * @url client/user.test 前端调用的url参数地址
	 */
	test: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------


		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},

};

module.exports = cloudObject;
